package com.hhf.feicodebackend.core;

import com.hhf.feicodebackend.ai.AiCodeGeneratorService;
import com.hhf.feicodebackend.ai.AiCodeGeneratorServiceFactory;
import com.hhf.feicodebackend.ai.model.enums.CodeGenTypeEnum;
import com.hhf.feicodebackend.ai.model.result.HtmlCodeResult;
import com.hhf.feicodebackend.ai.model.result.MultiFileCodeResult;
import com.hhf.feicodebackend.common.ErrorCode;
import com.hhf.feicodebackend.core.parser.CodeParserExecutor;
import com.hhf.feicodebackend.core.saver.CodeFileSaverExecutor;
import com.hhf.feicodebackend.exception.BusinessException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.io.File;

/**
 * @Author hhf
 * @Date 2025/8/11
 * @Description 门面类, 统一管理生成和保存文件的逻辑
 */
@Service
@Slf4j
public class AiCodeGeneratorFacade {

    @Resource
    private AiCodeGeneratorServiceFactory aiCodeGeneratorServiceFactory;


    /**
     * 统一路口:根据类型生成相应的代码
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     * @return
     */
    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenTypeEnum,Long appId) {

        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId);

        //1. 判断生成的类型是否存在
        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        //2. 选择相应的生成and保存方法
        return switch (codeGenTypeEnum) {
            case HTML -> {
                HtmlCodeResult htmlCodeResult = aiCodeGeneratorService.generateHtmlCode(userMessage);
                yield CodeFileSaverExecutor.execute(htmlCodeResult, CodeGenTypeEnum.HTML,appId);
            }
            case MULTI_FILE -> {
                MultiFileCodeResult multiFileCodeResult = aiCodeGeneratorService.generateMultiFileCode(userMessage);
                yield CodeFileSaverExecutor.execute(multiFileCodeResult, CodeGenTypeEnum.MULTI_FILE,appId);
            }
            default -> {
                String errorMessage = "不支持生成类型:" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };

    }

    /**
     * 统一路口:根据类型生成相应的代码(流式)
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     * @return
     */
    public Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenTypeEnum,Long appId) {

        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId);

        //1. 判断生成的类型是否存在
        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        //2. 选择相应的生成and保存方法
        return switch (codeGenTypeEnum) {
            case HTML -> {
                Flux<String> codeStream = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
                yield processCodeStream(codeStream,CodeGenTypeEnum.HTML,appId);
            }
            case MULTI_FILE -> {
                Flux<String> codeStream = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
                yield processCodeStream(codeStream,CodeGenTypeEnum.MULTI_FILE,appId);
            }
            default -> {
                String errorMessage = "不支持生成类型:" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };

    }

    /**
     * 通用流式代码处理方法
     *
     * @param codeStream
     * @param codeGenTypeEnum
     * @return
     */
    private Flux<String> processCodeStream(Flux<String> codeStream, CodeGenTypeEnum codeGenTypeEnum,Long appId) {
        StringBuilder codeBuilder = new StringBuilder();
        return codeStream.doOnNext(chunk -> {
            //实时收集代码
            codeBuilder.append(chunk);
        }).doOnComplete(() -> {
            try {
                //2. 解析字符串
                String codeContent = codeBuilder.toString();
                Object codeResult = CodeParserExecutor.execute(codeContent, codeGenTypeEnum);
                //3. 保存代码
                File saveDir = CodeFileSaverExecutor.execute(codeResult, codeGenTypeEnum,appId);
                //4. 日志记录
                log.info("保存成功,路径为:{}", saveDir.getAbsolutePath());
            } catch (Exception e) {
                log.error("保存失败,{}", e.getMessage());
            }
        });
    }



}
